package work.linruchang.util;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import org.springframework.aop.support.AopUtils;
import org.springframework.web.method.HandlerMethod;

import java.util.Optional;

/**
 * 增强的统一资源定位符处理的相关的工具
 *
 * @author LinRuChang
 * @version 1.0
 * @date 2021/06/28
 * @since 1.8
 **/
public class EnhanceUrlUtil extends URLUtil {

    /**
     * https://github.com/looly/hutool-site  ==>  https://github.com
     * 获取域名部分（含有协议前缀）
     * @param targetUrl 目标URL
     * @return
     */
    public static String getDomainName(String targetUrl) {
        return getDomainName(targetUrl,false);
    }

    /**
     * false：https://github.com/looly/hutool-site  ==>  https://github.com
     * true: https://github.com/looly/hutool-site  ==>  github.com
     * 获取域名部分
     * @param targetUrl 目标URL
     * @param isRemoveProtocolFlag 是否去掉前面的协议部分字符串
     * @return
     */
    public static String getDomainName(String targetUrl, boolean isRemoveProtocolFlag) {
        return Optional.ofNullable(targetUrl)
                .map(StrUtil::trim)
                .map(url -> {
                    if(StrUtil.startWith(targetUrl,"http")) {
                        int endIndex = StrUtil.indexOf(url, '/', StrUtil.indexOfIgnoreCase(url, "//") + 2);
                        String domainNameAndProtocolUrl = endIndex != -1 ? StrUtil.subPre(url, endIndex) : targetUrl;
                        return isRemoveProtocolFlag ? StrUtil.subAfter(domainNameAndProtocolUrl,"//",true) : domainNameAndProtocolUrl;
                    }
                    return null;
                })
                .orElse(null);
    }


    /**
     * 判断targetObj是否是HandlerMethod实例
     * @param targetObj
     * @return
     */
    public static boolean isHandlerMethod(Object targetObj) {
        if(targetObj != null){
            return targetObj instanceof HandlerMethod;
        }else {
            return false;
        }
    }

    /**
     * url拼接
     * @param headUrl 头url
     * @param suffixUrl 后缀url
     * @return  返回的结果以 /开头，不以/结束的url
     */
    public static String concatUrl(String headUrl, String suffixUrl) {
        headUrl = StrUtil.blankToDefault(headUrl, "");
        if (suffixUrl != null) {
            if (!suffixUrl.startsWith("/")) {
                if (!headUrl.endsWith("/")) {
                    suffixUrl = "/" + suffixUrl;
                }
            } else {
                if (headUrl.endsWith("/")) {
                    suffixUrl = suffixUrl.replaceFirst("/", "");
                }
            }
        }
        String allUrl = headUrl + suffixUrl;
        if (allUrl.endsWith("/")) {
            allUrl = allUrl.substring(0, allUrl.lastIndexOf("/"));
        }
        return allUrl;
    }

    /**
     * 根据RequestMapping注释，获取其中的Value值以及请求方式，并讲两者用分号分割
     *   分号前面的url地址是由Controller类上面的@RequestMapping与业务方法里面的@RequestMapping的Value拼接
     *     例如   /test/getData;POST
     * @param handlerMethod
     * @return
     */
    public static String getUrlAndMethod(HandlerMethod handlerMethod) {
        return String.format("%s;%s", getMethodUrl(handlerMethod),getRequestMethod(handlerMethod));
    }


    /**
     * 根据访问的URL映射的本地bean,获取数据库存储的url资源。
     *  由Controller类上面的@RequestMapping与业务方法里面的@RequestMapping的Value拼接而成
     * @param handlerMethod
     *            映射本地bean 的handle
     * @return
     */
    private static String getMethodUrl(HandlerMethod handlerMethod) {
        String regex = ".*value=\\[([^\\[\\]]*)\\].*method=\\[(.*?)\\].*";


        Object controllerBean = handlerMethod.getBean();
        Class controllerClass = null;
        if(AopUtils.isAopProxy(controllerBean)) {  //由于使用到ParamAspect切面，导致这个controllerBean是代理对象而非controller实例
            controllerClass = AopUtils.getTargetClass(controllerBean);
        }else {
            controllerClass = controllerBean.getClass();
        }

        String headUrl = ReflectClassUtils.getAnnoRequestMappingValue(controllerClass.getAnnotations());
        String suffixUrl = ReflectClassUtils.getAnnoRequestMappingValue(handlerMethod.getMethod().getAnnotations());
        return concatUrl(headUrl,suffixUrl);
    }

    /**
     * 获取请求方式【大写】
     *
     * @param handlerMethod
     *            映射本地bean 的handle
     * @return
     */
    private static String getRequestMethod(HandlerMethod handlerMethod) {
        return ReflectClassUtils.getAnnoRequestMappingMethod(handlerMethod.getMethod().getAnnotations());
    }


}
